package com.naiterui.ehp.bs.ds.modules.sys.service.impl;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.naiterui.ehp.bs.ds.common.constants.CacheConstants;
import com.naiterui.ehp.bs.ds.common.entity.BaseTree;
import com.naiterui.ehp.bs.ds.common.utils.Constant;
import com.naiterui.ehp.bs.ds.modules.sys.entity.Menu;
import com.naiterui.ehp.bs.ds.modules.sys.entity.User;
import com.naiterui.ehp.bs.ds.modules.sys.mapper.MenuMapper;
import com.naiterui.ehp.bs.ds.modules.sys.service.IMenuService;
import com.naiterui.ehp.bs.ds.modules.sys.service.IUserService;

@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IMenuService {

    @Autowired
    private IUserService userService;

    @Override
    public List<Menu> queryListByParentId(Long parentId) {
        return this.baseMapper.queryListParentId(parentId);
    }

    @Override
    @Cacheable(value = CacheConstants.MENU_LIST)
    public List<Menu> queryList() {
        QueryWrapper<Menu> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByAsc("order_num");
        List<Menu> menuList = super.list(queryWrapper);
        return BaseTree.listToTree(menuList);
    }

    @Override
    public List<Menu> queryNotButtonList() {
        List<Menu> menus = this.baseMapper.queryNotButtonList();
        // 添加顶级菜单
        Menu root = new Menu();
        root.setId(-1L);
        root.setName("一级菜单");
        root.setParentId(-2L);
        menus.add(root);
        return BaseTree.listToTree(menus);
    }

    @Override
    @Cacheable(value = CacheConstants.USER_MENU_LIST, key = "#userId")
    public List<Menu> getUserMenuList(Long userId) {
        // 系统管理员，拥有最高权限
        User user = this.userService.getById(userId);
        if (user.getRoleIdList().contains(Constant.SUPER_ADMIN)) {
            List<Menu> menus = this.baseMapper.queryNotButtonList();
            return BaseTree.listToTree(menus);
        }
        // 用户菜单列表
        List<Long> menuIdList = this.userService.queryAllMenuId(userId);
        Long[] ids = new Long[menuIdList.size()];
        menuIdList.toArray(ids);
        List<Menu> menus = this.baseMapper.getByIds(ids);
        List<Menu> rootMenus = this.queryRootMenus(menus);
        menus.addAll(rootMenus);
        return BaseTree.listToTree(menus);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = {CacheConstants.MENU_LIST, CacheConstants.USER_MENU_LIST, CacheConstants.MENU_ALL, CacheConstants.USER, CacheConstants.PERMISSION_CACHE_PREFIX}, allEntries = true)
    public void delete(Long menuId) {
        // 删除菜单
        super.removeById(menuId);
        // 删除菜单与角色关联
        Menu menu = new Menu();
        menu.setId(menuId);
        super.remove(new QueryWrapper<>(menu));
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = {CacheConstants.MENU_LIST, CacheConstants.USER_MENU_LIST, CacheConstants.MENU_ALL, CacheConstants.USER, CacheConstants.PERMISSION_CACHE_PREFIX}, allEntries = true)
    public boolean save(Menu menu) {
        return super.save(menu);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = {CacheConstants.MENU_LIST, CacheConstants.USER_MENU_LIST, CacheConstants.MENU_ALL, CacheConstants.USER, CacheConstants.PERMISSION_CACHE_PREFIX}, allEntries = true)
    public boolean updateById(Menu menu) {
        return super.updateById(menu);
    }

    private List<Menu> queryRootMenus(List<Menu> list) {
        Set<Long> parentIdSet = list.stream().map(BaseTree::getParentId).collect(Collectors.toSet());
        Set<Long> idSet = list.stream().map(BaseTree::getId).collect(Collectors.toSet());
        parentIdSet.removeAll(idSet);
        Long[] ids = new Long[parentIdSet.size()];
        parentIdSet.toArray(ids);
        return this.baseMapper.getByIds(ids);
    }

}
